﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Data.Objects;
using SimpleData.Infrastructure.Tenancy;

namespace SimpleData.Data
{
	/// <summary>
	/// 
	/// </summary>
	public static class QueryableExtensions
	{

		/// <summary>
		/// Método helper que auxiliar a carregar por eagerLoad as propriedades da entidade
		/// </summary>
		/// <typeparam name="TEntity"></typeparam>
		/// <param name="query"></param>
		/// <param name="property"></param>
		/// <returns></returns>
		public static IQueryable<TEntity> EagerLoad<TEntity>( this IQueryable<TEntity> query, Expression<Func<TEntity, object>> property )
			where TEntity : class
		{
			ObjectSet<TEntity> set = query.ToObjectSet();
			set.Include( property.GetPropertyName() );
			return set;
		}

		/// <summary>
		/// Não carrega para o contexto do entity as entidades materializadas
		/// </summary>
		/// <param name="query"></param>
		/// <returns></returns>
		public static IQueryable<TEntity> NoTracking<TEntity>( this IQueryable<TEntity> query )
			where TEntity : class
		{
			var set = query.ToObjectSet();
			set.MergeOption = MergeOption.NoTracking;
			return set;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="TEntity"></typeparam>
		/// <param name="query"></param>
		/// <returns></returns>
		public static IQueryable<TEntity> AlwaysLoad<TEntity>( this IQueryable<TEntity> query )
			where TEntity : class
		{
			var set = query.ToObjectSet();
			set.MergeOption = MergeOption.OverwriteChanges;
			return set;
		}

		private static ObjectSet<TEntity> ToObjectSet<TEntity>( this IQueryable<TEntity> query )
			where TEntity : class
		{
			return ( ObjectSet<TEntity> )query;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="TEntity"></typeparam>
		/// <param name="query"></param>
		/// <returns></returns>
		public static IQueryable<TEntity> PerTenant<TEntity>( this IQueryable<TEntity> query )
			where TEntity : class, IObjectPerTenant
		{
			// TODO : Adicionar critério por Tenant
			if ( typeof( IObjectPerTenant ).IsAssignableFrom( typeof( TEntity ) ) )
				return query.Where( e => e.ApplicationID == 1 );
			else
				return query;
		}
	}
}
